Skip to content

test(client): add round-trip/known-answer tests for G1/G2 byte encodings - #347

Open
theo372001 wants to merge 1 commit into
crackedstudio:mainfrom
theo372001:test/issue-48-g1-g2-encoding-tests
Open

test(client): add round-trip/known-answer tests for G1/G2 byte encodings#347
theo372001 wants to merge 1 commit into
crackedstudio:mainfrom
theo372001:test/issue-48-g1-g2-encoding-tests

Conversation

@theo372001

Copy link
Copy Markdown

What changed

Adds round-trip/known-answer tests for feToBytes, g1ToBytes, g2ToBytes, and verificationKeyToContractFormat in packages/client/src/prove.ts, and exports those helpers so they're testable.

While implementing this I found that feToBytes/g1ToBytes/g2ToBytes/verificationKeyToContractFormat (plus generateProof, CircuitInput, ContractProof, ContractVerificationKey) had been silently dropped from prove.ts by an unrelated prior change (the issue #123 artifact-prefetch rewrite in ce70090). That left contract.ts, app/src/hooks/useCircleFlow.ts, scripts/e2e.ts, and the existing prove.test.ts all importing names that no longer existed — the package couldn't typecheck or run its test file at all. I restored those exports (merged alongside the newer prefetch-based fullProve/prove) so the package is internally consistent again and the functions this issue asks to test actually exist to test.

Two more small, necessary fixes surfaced while getting the suite to actually run:

  • config.ts re-exports TREE_LEVELS/MAX_CIRCLE_SIZE from tree.ts, but they'd also been dropped from tree.ts in an unrelated earlier merge. Restored (2 lines) since prove.ts's validateCircuitInput/generateProof default to TREE_LEVELS.
  • artifacts.ts had an unguarded top-level prefetchMembershipArtifacts() call that fires a real fetch("/circuits/membership.wasm") on any import of prove.ts — it crashed every test run (and the whole file was already redundant with prove.ts's own lazy, memoized getArtifacts()). Removed the stray call.

None of these three restorations touch the intended behavior of prior PRs — they just make the already-committed types/functions/tests load and run again.

Why

Closes #48

feToBytes, g1ToBytes, g2ToBytes implement the exact wire format the contract deserializes (G1 = 96 bytes X||Y, G2 = 192 bytes Xc1||Xc0||Yc1||Yc0). This confirms reality matches that description: g1ToBytes places X in bytes 0-47 and Y in 48-95; g2ToBytes places the limbs in Xc1||Xc0||Yc1||Yc0 order exactly as documented (Xc1 before Xc0 — the counterintuitive part).

Testing

  • Circuit tests (cd circuits && npm test)
  • Contract tests (cd contracts && cargo test)
  • E2E against testnet (npm run e2e)
  • App tested manually (cd app && npm run dev)
  • Docs-only (no code changed)

Ran the client package's test suite directly (node --import tsx --test src/*.test.ts from packages/client — the way these node:test-based test files actually execute; npm test there is wired to vitest run, which doesn't recognize node:test's test() and reports 0 tests for every file in the package, pre-existing and unrelated to this PR):

  • prove.test.ts: 29/29 passing (21 pre-existing + 8 new: 3 feToBytes, 2 g1ToBytes, 2 g2ToBytes, 1 round-trip).
  • Full package suite before this change: 47 tests, 31 pass / 16 fail (prove.test.ts failed to even load — missing exports).
  • Full package suite after this change: 75 tests, 60 pass / 15 fail. The 15 remaining failures are pre-existing and unrelated to prove.ts (contract.test.ts x2, identity.test.ts x7, tree.test.ts x6 — all failing for reasons unconnected to this change, e.g. tree.proofOf is not a function). Same failures, same count, present before and after.

Acceptance criterion verified: temporarily swapped the Xc1/Xc0 write order in g2ToBytes and reran — not ok 28 - g2ToBytes places limbs in Xc1||Xc0||Yc1||Yc0 order (28 pass / 1 fail). Reverted the swap and reran — clean 29 pass / 0 fail.

feToBytes, g1ToBytes, g2ToBytes, and verificationKeyToContractFormat had
been silently dropped from prove.ts by an unrelated prior change (the
issue crackedstudio#123 artifact-prefetch rewrite), which broke every consumer that
still imported them (contract.ts, useCircleFlow.ts, scripts/e2e.ts,
prove.test.ts). Restore them alongside the new prefetch-based
fullProve/prove, and export feToBytes/g1ToBytes/g2ToBytes so the exact
wire format the contract deserializes can be pinned with tests.

Add:
- feToBytes known-answer tests (0, 1, and the max canonical Fp value —
  the BLS12-381 base field modulus - 1), always 48 bytes.
- g1ToBytes length + limb placement (X in bytes 0-47, Y in 48-95).
- g2ToBytes length + limb placement, pinning the Xc1||Xc0||Yc1||Yc0
  order specifically (verified: a deliberate Xc1/Xc0 swap makes this
  test fail; reverting makes the suite pass clean again).
- A round-trip test against the committed circuits/verification_key.json
  asserting ic.length === 4 for 3 public signals, correct byte lengths
  for every field, and byte-for-byte agreement with direct
  g1ToBytes/g2ToBytes calls on the same JSON.

Also restores TREE_LEVELS/MAX_CIRCLE_SIZE to tree.ts (config.ts's
re-export of them was broken the same way) and drops an unguarded
top-level prefetchMembershipArtifacts() call in artifacts.ts that fired
a real fetch() on any import of prove.ts, crashing under Node/tests —
both were blocking prove.ts and its test suite from loading at all.

Closes crackedstudio#48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add round-trip/known-answer tests for the G1/G2 byte encodings in prove.ts

1 participant